package com.vecspace.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

import com.vecspace.exception.ErrMsg;
import com.vecspace.exception.HException;


public class DateTimeUtil {

	/**返回指定周次的周一和周日的日期
	 * @param year 年份
	 * @param week 周次 从1开始，第一周可能跨年
	 * @return  Date[周一的日期，周日的日期]	 
	 * @author: wanghua
	 */
	public static Date[] getDateOfWeek(int year, int week){
		Date[] dateArr = new Date[2];
		Calendar c = new GregorianCalendar();
		c.set(Calendar.YEAR, year);
		c.set(Calendar.WEEK_OF_YEAR, week);		 
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		dateArr[0] = c.getTime();
		c.add(Calendar.DAY_OF_WEEK, 6);
		dateArr[1] = c.getTime();
		return dateArr;
	}

	final static String ISO_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
	/**将ISO 8601格式的日期字符串转为Date对象 yyyy-MM-dd'T'HH:mm:ss.SSSXXX <br>
	 *比如 2021-11-15T14:20:30.123+08:00
	 * @param isoDateString
	 * @author wanghua
	 * @date 2021/11/13  11:22
	 * @return java.util.Date
	 **/
	public static Date parseIsoDate(String isoDateString) throws ParseException {
		SimpleDateFormat df = new SimpleDateFormat(ISO_PATTERN);
		Date date = df.parse(isoDateString);
		return date;
	}

	/**把date对象格式化为ISO 8601的时间格式的字符串 yyy-MM-dd'T'HH:mm:ss.SSSXXX <br>
	 * 比如 2021-11-15T14:20:30.123+08:00
	 * @param date
	 * @author wanghua
	 * @date 2021/11/13  11:25
	 * @return java.lang.String
	 **/
	public static String formatToIsoDate(Date date){
		SimpleDateFormat df = new SimpleDateFormat(ISO_PATTERN);
		String isoDateStr = df.format(date);
		return isoDateStr;
	}

	/**
	 * 把各种字符串格式的日期转为日期对象
	 * yyyy-MM-dd     yyyy-M-d     yyyy-MM-dd HH:mm:ss
	 * yyyy/MM/dd     yyyy/M/d     yyyy/MM/dd HH:mm:ss
	 * yyyy年MM月dd日   yyyy年M月d日    yyyy年MM月dd日 HH时mm分ss秒
	 * 功能描述：
	 * @param datestring
	 * @author: wanghua
	 */
	public static Date parseDate(String datestring) throws ParseException{
		if(datestring == null || datestring.length()<6)return null;
		Date datetime = null;
		java.util.regex.Pattern pattern=java.util.regex.Pattern.compile("^(\\-|\\+)?\\d+?$"); //("[0-9]*");  正数负数都可以，正负数以1970-1-1为分界线
        java.util.regex.Matcher match=pattern.matcher(datestring);//时间戳格式
        if(match.matches()==true)
        {
        	long timeticks = Long.parseLong(datestring);
        	datetime = new Date(timeticks);             
        }else{ //下面的判断最好改成正则表达式，但目前这样简单处理也能满足大部分情况。
        	String datepattern = getDatePattern(datestring);
			if(datepattern.length()>0){
				SimpleDateFormat sdf = new SimpleDateFormat(datepattern);
				datetime = sdf.parse(datestring);
			}else{
				SimpleDateFormat sdf = new SimpleDateFormat();
				datetime = sdf.parse(datestring);
			}
        }
        return datetime;
	}
	public static String getDatePattern(String dateValue){
		if(StringUtils.contains(dateValue, "T")){
			return ISO_PATTERN;
		}
		String datePattern="";
		int len = StringUtils.countMatches(dateValue, "/");
		if (len == 2) {
			datePattern = "yyyy/MM/dd";
		} else if (len == 1) {
			datePattern = "yyyy/MM";
		}  else if (len == 1) {
			datePattern = "yyyy/MM";
		} else if ((len = StringUtils.countMatches(dateValue, "-")) == 2) {
			datePattern = "yyyy-MM-dd";
		} else if (len == 1) {
			datePattern = "yyyy-MM";
		} else if (StringUtils.contains(dateValue, "日")) {
			len=2;
			datePattern = "yyyy年MM月dd日";
		} else if (StringUtils.contains(dateValue, "月")) {
			len=1;
			datePattern = "yyyy年MM月";
		} else if (StringUtils.contains(dateValue, "年")) {
			len=1;
			datePattern = "yyyy年";
		} else if(StringUtils.isNumeric(dateValue)){
			datePattern = "yyyy";
			len=1;
		}
		if(StringUtils.contains(dateValue, "T")){
			dateValue=dateValue.replace("T", " ");
		}
		if (len == 2&&StringUtils.contains(dateValue, " ")) {
			len = StringUtils.countMatches(dateValue, ":");
			datePattern+=" ";
			if (len == 2) {
				datePattern += "HH:mm:ss";
			} else if (len == 1) {
				datePattern += "HH:mm";
			} else if (StringUtils.contains(dateValue, "秒")) {
				datePattern += "HH时mm分ss秒";
			} else if (StringUtils.contains(dateValue, "分")) {
				datePattern += "HH时mm分";
			} else if (StringUtils.contains(dateValue, "时")) {
				datePattern += "HH时";
			}else {
				datePattern += "HH";
			}
		}
		return datePattern;
	}
	/**
	 * 求两个日期间的月份集合
	 * @param sDate 开始时间
	 * @param fDate 结束时间
	 * @return
	 * @throws ParseException
	 */
	public static List<String> getAllMonths(String sDate,String fDate) throws Exception {
		if (sDate.compareTo(fDate) > 0) {
			//start大于end日期时互换
			String temp = sDate;
			sDate = fDate;
			fDate = temp;
		}
		List<String> list = new ArrayList<String>();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM");
		Date startDate = sf.parse(sDate); // 开始日期
		Date endDate = sf.parse(fDate); // 结束日期
		Calendar startCalendar = Calendar.getInstance();
		Calendar endCalendar = Calendar.getInstance();
		startCalendar.setTime(startDate);
		endCalendar.setTime(endDate);
		String result = null;
		while (startCalendar.compareTo(endCalendar) <= 0) {
			startDate = startCalendar.getTime();
			result = sf.format(startDate);
			list.add(result);
			// 开始日期加一个月直到等于结束日期为止
			startCalendar.add(Calendar.MONTH, 1);
		}
		return list;
	}
	
	/**
	 * 求两个日期间的年份集合
	 * @param sDate 开始时间
	 * @param fDate 结束时间
	 * @return
	 * @throws ParseException
	 */
	public static List<String> getAllYears(String sDate,String fDate) throws Exception {
		if (sDate.compareTo(fDate) > 0) {
			//start大于end日期时互换
			String temp = sDate;
			sDate = fDate;
			fDate = temp;
		}
		List<String> list = new ArrayList<String>();
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM");
		SimpleDateFormat sfYear = new SimpleDateFormat("yyyy");
		Date startDate = sf.parse(sDate); // 开始日期
		Date endDate = sf.parse(fDate); // 结束日期
		Calendar startCalendar = Calendar.getInstance();
		Calendar endCalendar = Calendar.getInstance();
		startCalendar.setTime(startDate);
		endCalendar.setTime(endDate);
		 
		while (startCalendar.compareTo(endCalendar) <= 0) {
			startDate = startCalendar.getTime();
			String year = sfYear.format(startDate);
			if(!list.contains(year)){
				list.add(year);
			}
			// 开始日期加一个月直到等于结束日期为止
			startCalendar.add(Calendar.MONTH, 1);
		}
		return list;
	}
	
	public static String formatDate(Date date, String format){
		if(date == null)return "";
		SimpleDateFormat sf = new SimpleDateFormat(format);
		return sf.format(date);
	}
	
	public static String formatDateTime(Date date){
		if(date == null)return "";
		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return sf.format(date);
	}
	
	/**比较两个date是否相等（根据getTime()判断），相等返回true
	 * 注意：如果date1和date2都是null，返回true
	 * @param date1
	 * @param date2
	 * @return 
	 * @author: wanghua
	 */
	public static boolean equals(Date date1, Date date2) {
		if(date1 == null && date2 == null)return true;
		if(date1 == null || date2 == null)return false;
		return date1.getTime() == date2.getTime();
	}
	
	/**比较两个date是否是同一天（日历日相等，时分秒不做比较），相等返回true
	 * 注意：如果date1和date2都是null，返回true
	 * @param date1
	 * @param date2
	 * @return 
	 * @author: wanghua
	 */
	public static boolean equalsDate(Date date1, Date date2) {
		if(date1 == null && date2 == null)return true;
		if(date1 == null || date2 == null)return false;
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.setTime(date1);
		c2.setTime(date2);
		
		boolean equalYear = c1.get(Calendar.YEAR) ==  c2.get(Calendar.YEAR);
		boolean equalMonth = c1.get(Calendar.MONTH) ==  c2.get(Calendar.MONTH);
		boolean equalDate = c1.get(Calendar.DAY_OF_MONTH) ==  c2.get(Calendar.DAY_OF_MONTH);
		return equalYear && equalMonth && equalDate;
	}
	
	/**把date的时分秒设为 0:0:0
	 * 
	 * @param date
	 * @return 
	 * @author: wanghua
	 */
	public static Date setDateFirstSecond(Date date) {
		if(date == null)return null;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	
	/**把date的时分秒设为 23:59:59
	 * 
	 * @param date
	 * @return 
	 * @设计者: wanghua
	 * @author: wanghua
	 * @reviewer: 
	 * @author: wanghua
	 */
	public static Date setDateLastSecond(Date date) {
		if(date == null)return null;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}
	
	/**获取一个月的最后一天，并且时分秒设置为 23:59:59<br>
	 * getlastDateOfMonth(2018, 2) 输出 2018-02-28 23:59:59
	 * @param year 4位数字，比如 2018
	 * @param month 1-12
	 * @return 
	 * @author: wanghua
	 */
	public static Date getlastDateOfMonth(int year, int month) throws HException {
		Assert.throwz(month >= 1 && month <= 12, "月份不正确，应该是1-12");
		Calendar calendar = Calendar.getInstance();
	      // 设置时间,当前时间不用设置
	    calendar.set(Calendar.YEAR, year);
	    //要先设置为1日，否则在设置月份的时候，如果那个月份没有这个日期，设置的月份数会不正确
	    //比如在 2018-12-31 的基础上，设置 Calendar.MONTH为1的话，输出的日期为 2018-03-03
	    calendar.set(Calendar.DAY_OF_MONTH, 1); 
	    calendar.set(Calendar.MONTH, month - 1);
	    calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
	    
	    calendar.set(Calendar.HOUR_OF_DAY, 23);
	    calendar.set(Calendar.MINUTE, 59);
	    calendar.set(Calendar.SECOND, 59);
	    calendar.set(Calendar.MILLISECOND, 999);
		
	    return calendar.getTime();
	}

	/**根据年月获取该月的天数，
	 *
	 * @param year
	 * @param month
	 * @return yyyy-MM-dd
	 */
	public static int getLastDayOfMonth(int year, int month){
		Assert.throwz(month >= 1 && month <= 12, "月份不正确，应该是1-12");
		Calendar calendar = Calendar.getInstance();
		// 设置时间,当前时间不用设置
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month - 1);
		int lastDay = calendar.getActualMaximum(Calendar.DATE);
		return lastDay;
	}

	/**根据年月获取该月最后一天的日期，
	 *
	 * @param year
	 * @param month
	 * @return yyyy-MM-dd
	 */
	public static String getLastDateStrOfMonth(int year, int month){
		Assert.throwz(month >= 1 && month <= 12, "月份不正确，应该是1-12");
		Calendar calendar = Calendar.getInstance();
		// 设置时间,当前时间不用设置
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, month - 1);
		int lastDay = calendar.getActualMaximum(Calendar.DATE);
		calendar.set(Calendar.DAY_OF_MONTH, lastDay);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		return sdf.format(calendar.getTime());
	}
	/**返回日期的数字格式：yyyyMMdd
	 * 
	 * @param date
	 * @return
	 */
	public static int getDateNum(Date date) {
		if(date == null) return -99999999;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int dateNum = calendar.get(Calendar.YEAR) * 10000 + (calendar.get(Calendar.MONTH) + 1) * 100 + calendar.get(Calendar.DAY_OF_MONTH);
		return dateNum;// yyyyMMdd
	}
	
	/**比较两个日期（只比较日期部分，不比较时间部分）
	 * 
	 * @param startDate
	 * @param endDate
	 * @param allowNull 当允许为空时，startDate，endDate任意一个为null，都返回true
	 * @param errmsg 用于回传错误信息，可以为null
	 * @return 
	 * @author: wanghua
	 */
	public static boolean checkDateRange(Date startDate, Date endDate, boolean allowNull, ErrMsg errmsg) {
		if(!allowNull) {
			if(startDate == null) {
				if(errmsg != null) {
					errmsg.setMsg("起始日期不能为空");
				}
				return false;	
			}
			if(endDate == null) {
				if(errmsg != null) {
					errmsg.setMsg("截止日期不能为空");
				}
				return false;		
			}
		}else {
			if(startDate == null || endDate == null) {
				return true;
			}
		}
		Calendar c1 = Calendar.getInstance();
		c1.setTime(startDate);
		
		Calendar c2 = Calendar.getInstance();
		c2.setTime(endDate);
		
		int d1 = c1.get(Calendar.YEAR) * 10000 + c1.get(Calendar.MONTH)* 100 + c1.get(Calendar.DATE);
		int d2 = c2.get(Calendar.YEAR) * 10000 + c2.get(Calendar.MONTH)* 100 + c2.get(Calendar.DATE);
		return d1 <= d2;		
	}
	/**比较两个日期（只比较日期部分，不比较时间部分）
	 * 
	 * @param startDate
	 * @param endDate
	 * @param allowNull 当允许为空时，startDate，endDate任意一个为null，都返回true
	 * @param errmsg 用于回传错误信息，可以为null
	 * @return 
	 * @author: wanghua
	 */
	public static boolean checkDateTimeRange(Date startDate, Date endDate, boolean allowNull, ErrMsg errmsg) {
		if(!allowNull) {
			if(startDate == null) {
				if(errmsg != null) {
					errmsg.setMsg("起始日期不能为空");
				}
				return false;	
			}
			if(endDate == null) {
				if(errmsg != null){
					errmsg.setMsg("截止日期不能为空");
				}
				return false;		
			}
		}else {
			if(startDate == null || endDate == null) {
				return true;
			}
		}
				
		long d1 = startDate.getTime();
		long d2 = endDate.getTime();
		return d1 <= d2;		
	}
	/**根据距离当前时间的远近，返回不同的时间格式MM/dd HH:mm or yyyy/MM/dd
	 * 
	 * @param date
	 * @return 
	 * @author: wanghua
	 */
	public static String formatSimpleDateTimeByNow(Date date) {
		if(date == null)return "";
		Date now = new Date();
		long mills = now.getTime() - date.getTime();
		double days = mills / 1000.0 / 60 / 60 / 24;
		if(days < 8) {
			String timestr = new java.text.SimpleDateFormat("MM/dd HH:mm").format(date);
			return timestr;
		}else{
			String timestr = new java.text.SimpleDateFormat("yyyy/MM/dd").format(date);
			return timestr;
		}
	}
}
